import 'package:dio/dio.dart' as dio_pkg;
import 'package:get/get.dart';

/// 自定义异常类 - Custom exception class
/// 用于统一处理API请求中的各种异常情况
class ApiException implements Exception {
  /// 错误消息 - Error message
  final String message;
  
  /// HTTP状态码 - HTTP status code
  final int? statusCode;
  
  /// 响应数据 - Response data
  final dynamic data;

  ApiException(this.message, {this.statusCode, this.data});

  @override
  String toString() => message;
}

/// API服务基础类 - Base API service class
/// 提供网络请求的基础封装，包括错误处理、超时设置、拦截器等
/// 遵循单一职责原则，仅负责网络请求的基础功能
class ApiService extends GetxService {
  static ApiService get to => Get.find();

  late dio_pkg.Dio _dio;
  
  /// 基础URL - Base URL
  final String baseUrl = 'http://192.168.31.17:3000/api';

  @override
  void onInit() {
    super.onInit();
    _initializeDio();
  }

  /// 初始化Dio实例 - Initialize Dio instance
  /// 配置基础参数、超时时间、请求头等
  void _initializeDio() {
    _dio = dio_pkg.Dio(
      dio_pkg.BaseOptions(
        baseUrl: baseUrl,
        connectTimeout: const Duration(seconds: 10),
        receiveTimeout: const Duration(seconds: 10),
        headers: {'Content-Type': 'application/json'},
      ),
    );

    // 添加错误处理拦截器 - Add error handling interceptor
    _dio.interceptors.add(
      dio_pkg.InterceptorsWrapper(
        onError: (dio_pkg.DioException err, handler) {
          final apiError = _handleDioError(err);
          return handler.reject(
            dio_pkg.DioException(
              requestOptions: err.requestOptions,
              error: apiError,
              type: err.type,
              response: err.response,
            ),
          );
        },
      ),
    );
  }

  /// 处理Dio异常 - Handle Dio exceptions
  /// 将各种网络异常转换为统一的ApiException
  /// @param err Dio异常对象
  /// @return ApiException 统一的异常对象
  ApiException _handleDioError(dio_pkg.DioException err) {
    String message = '网络请求失败';
    int? statusCode = err.response?.statusCode;

    switch (err.type) {
      case dio_pkg.DioExceptionType.connectionTimeout:
        message = '连接超时，请检查网络';
        break;
      case dio_pkg.DioExceptionType.receiveTimeout:
        message = '响应超时，请稍后重试';
        break;
      case dio_pkg.DioExceptionType.badResponse:
        message = _handleHttpError(statusCode, err.response?.data);
        break;
      case dio_pkg.DioExceptionType.cancel:
        message = '请求已取消';
        break;
      case dio_pkg.DioExceptionType.unknown:
        message = '网络异常，请检查网络连接';
        break;
      default:
        message = '未知网络错误';
    }

    return ApiException(
      message,
      statusCode: statusCode,
      data: err.response?.data,
    );
  }

  /// 处理HTTP状态码错误 - Handle HTTP status code errors
  /// @param statusCode HTTP状态码
  /// @param responseData 响应数据
  /// @return String 错误消息
  String _handleHttpError(int? statusCode, dynamic responseData) {
    switch (statusCode) {
      case 400:
        return '请求参数错误';
      case 401:
        return '未授权访问，请先登录';
      case 403:
        return '访问被禁止';
      case 404:
        return '请求的资源不存在';
      case 409:
        return '请求冲突，请稍后重试';
      case 500:
        return '服务器内部错误';
      case 502:
        return '网关错误';
      case 503:
        return '服务暂时不可用';
      default:
        // 尝试从响应数据中获取错误消息
        if (responseData is Map && responseData['message'] != null) {
          return responseData['message'];
        }
        return '请求失败 (状态码: $statusCode)';
    }
  }

  /// 通用GET请求方法 - Generic GET request method
  /// @param path 请求路径
  /// @param queryParameters 查询参数
  /// @return Future<dio_pkg.Response> 响应对象
  /// @throws ApiException 当请求失败时抛出
  Future<dio_pkg.Response> get(
    String path, {
    Map<String, dynamic>? queryParameters,
  }) async {
    try {
      return await _dio.get(path, queryParameters: queryParameters);
    } on dio_pkg.DioException catch (e) {
      if (e.error is ApiException) {
        throw e.error as ApiException;
      }
      throw ApiException('GET请求失败: ${e.message}');
    }
  }

  /// 通用POST请求方法 - Generic POST request method
  /// @param path 请求路径
  /// @param data 请求数据
  /// @param queryParameters 查询参数
  /// @return Future<dio_pkg.Response> 响应对象
  /// @throws ApiException 当请求失败时抛出
  Future<dio_pkg.Response> post(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
  }) async {
    try {
      return await _dio.post(
        path,
        data: data,
        queryParameters: queryParameters,
      );
    } on dio_pkg.DioException catch (e) {
      if (e.error is ApiException) {
        throw e.error as ApiException;
      }
      throw ApiException('POST请求失败: ${e.message}');
    }
  }

  /// 通用PUT请求方法 - Generic PUT request method
  /// @param path 请求路径
  /// @param data 请求数据
  /// @param queryParameters 查询参数
  /// @return Future<dio_pkg.Response> 响应对象
  /// @throws ApiException 当请求失败时抛出
  Future<dio_pkg.Response> put(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
  }) async {
    try {
      return await _dio.put(
        path,
        data: data,
        queryParameters: queryParameters,
      );
    } on dio_pkg.DioException catch (e) {
      if (e.error is ApiException) {
        throw e.error as ApiException;
      }
      throw ApiException('PUT请求失败: ${e.message}');
    }
  }

  /// 通用DELETE请求方法 - Generic DELETE request method
  /// @param path 请求路径
  /// @param queryParameters 查询参数
  /// @return Future<dio_pkg.Response> 响应对象
  /// @throws ApiException 当请求失败时抛出
  Future<dio_pkg.Response> delete(
    String path, {
    Map<String, dynamic>? queryParameters,
  }) async {
    try {
      return await _dio.delete(path, queryParameters: queryParameters);
    } on dio_pkg.DioException catch (e) {
      if (e.error is ApiException) {
        throw e.error as ApiException;
      }
      throw ApiException('DELETE请求失败: ${e.message}');
    }
  }

  /// 设置认证令牌 - Set authentication token
  /// @param token 认证令牌
  void setAuthToken(String token) {
    _dio.options.headers['Authorization'] = 'Bearer $token';
  }

  /// 清除认证令牌 - Clear authentication token
  void clearAuthToken() {
    _dio.options.headers.remove('Authorization');
  }

  /// 获取当前基础URL - Get current base URL
  String get currentBaseUrl => baseUrl;

  /// 检查网络连接状态 - Check network connection status
  /// @return Future<bool> 连接状态，true表示连接正常
  Future<bool> checkConnection() async {
    try {
      final response = await _dio.get('/health');
      return response.statusCode == 200;
    } catch (e) {
      return false;
    }
  }

  /// 取消所有请求 - Cancel all requests
  void cancelRequests() {
    _dio.close(force: true);
  }
}
